package com.yc.annotation.database;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MysqlTracker {
	private List<String> classNames = new ArrayList<String>();
	
	public static void main(String[] args) {
		MysqlTracker mt = new MysqlTracker();
		try {
			mt.startTracker("com.yc.annotation.bean");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private boolean startTracker(String basePackage) throws Exception {
		URL url = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/"));

		String path = url.getPath();
		try {
			path = URLDecoder.decode(path, "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		File dest = new File(path);
		getClassInfo(basePackage, dest);
		
		classNames.forEach(System.out::println);
		List<String> sqlList = doTracker();
		
		sqlList.forEach(System.out::println);
		return false;
	}

	/**
	 * 解析得到要执行的sql语句
	 * @return
	 * @throws ClassNotFoundException 
	 */
	private List<String> doTracker() throws Exception {
		if(classNames.isEmpty()) {
			return Collections.emptyList();
		}
		List<String> tableList = new ArrayList<String>(); // 建表的语句
		List<String> clist = new ArrayList<String>(); // 创建约束的语句
		
		Type type = null;
		ForeignKey foreignKey = null;
		String sql = null;
		Field[] fields;
		Class<?> cls = null;
		StringBuffer sqlSbf = null;
		String tableName = null;
		String typeName = null;
		Class<?> fieldType = null;
		String temp = null;
		StringBuffer fsql = null;
		
		for(String className : classNames) {
			cls = Class.forName(className); // 加载这个类
			
			// 说明这个类不需要创建对应的表
			if(!cls.isAnnotationPresent(Table.class)) {
				continue;
			}
			
			sqlSbf = new StringBuffer();
			sqlSbf.append("create table ");
			
			tableName = cls.getAnnotation(Table.class).name(); // 获取用户指定的表名
			if(tableName == null || "".equals(tableName)) {// 说明用户没有指定表名
				// 则默认用类名所有字母小写为表名
				tableName = cls.getSimpleName().toLowerCase();
			}
			sqlSbf.append(tableName).append("("); // 后面开始拼接字段
			
			fields = cls.getDeclaredFields(); // 获取类中的所有属性
			
			if(fields == null || fields.length <= 0) {
				continue;
			}
			
			for(Field fd : fields) {
				if(!fd.isAnnotationPresent(Type.class) && !fd.isAnnotationPresent(PrimaryKey.class)
						&& !fd.isAnnotationPresent(ForeignKey.class)) {
					continue; // 说明此属性不要生成对应的列
				}
				
				type = fd.getAnnotation(Type.class);
				sqlSbf.append(fd.getName()); // 拼接列名
				
				//System.out.println(sqlSbf);
				typeName = type.type(); // 获取用户指定的类型
				if(type == null || typeName == null || "".equals(typeName)) {
					
					// 说明用户没有指定类型
					fieldType = fd.getType(); // 获取这个属性的类型
					if(Integer.class == fieldType || Integer.TYPE == fieldType) {
						sqlSbf.append(" int ");
					}else if(Long.class == fieldType || Long.TYPE == fieldType) {
						sqlSbf.append(" bigint ");
					}else if(Double.class == fieldType || Double.TYPE == fieldType 
							|| Float.class == fieldType || Float.TYPE == fieldType) {
						sqlSbf.append(" decimal(10, 2) ");
					}else {
						sqlSbf.append(" varchar(100) ");
					}
				}else {
					typeName = type.type();
					sqlSbf.append(" ").append(typeName).append(" ");
				}
				
				// 拼接约束
				if(fd.isAnnotationPresent(PrimaryKey.class)) {
					sqlSbf.append("primary key");
					
					if(fd.getAnnotation(PrimaryKey.class).autoIncrement()) {
						sqlSbf.append(" auto_increment");
					}
				}else if(type != null) {
					if(!type.constraints().allowNull()) {
						sqlSbf.append("not null");
					}
					
					if(type.constraints().unique()) {
						sqlSbf.append(" unique");
					}
					
					temp = type.constraints().defaults();
					if(temp != null && !"".equals(temp)) { // 说明有默认约束
						sqlSbf.append(" default ").append(temp);
					}
				}
				sqlSbf.append(", ");
				
				//判断这个字段上有没有外键约束
				if(fd.isAnnotationPresent(ForeignKey.class)) {
					fsql = new StringBuffer();
					foreignKey = fd.getAnnotation(ForeignKey.class);
					temp = foreignKey.reference_column(); // 获取引用列名
					if(temp == null || "".equals(temp)) {
						temp = fd.getName();
					}
					fsql.append("alter table ").append(tableName).append(" add constraint FK_").append(tableName).append("_")
					.append(System.currentTimeMillis()).append(" foreign Key(").append(fd.getName())
					.append(") references ").append(foreignKey.reference_table()).append("(").append(temp).append(")");
					clist.add(fsql.toString());
				}
			}
			sql = sqlSbf.toString();
			sql = sql.substring(0, sql.lastIndexOf(","));
			sql += ") ENGINE=InnoDB default charset=utf8 collate=utf8_bin";
			tableList.add(sql);
		}
		tableList.addAll(clist);
		return tableList;
	}

	/**
	 * 获取指定包下的所有类
	 * @param basePackage
	 * @param dest
	 */
	private void getClassInfo(String basePackage, File dest) {
		if(dest.exists() && dest.isDirectory()) {
			for(File fl : dest.listFiles()) {// 遍历这个目录下的所有文件
				if(fl.isDirectory()) {
					getClassInfo(basePackage + "." + fl.getName(), fl);
					continue;
				}
				classNames.add(basePackage + "." + fl.getName().replace(".class", ""));
			}
			
		}
		
	}
	
	
}
